package com.example.demo.generator.scaffold.registry;

import com.example.demo.generator.scaffold.model.TemplateContext;
import com.example.demo.generator.scaffold.model.TemplateDescriptor;
import com.example.demo.generator.scaffold.util.ScaffoldNameUtils;

import java.util.List;

/**
 * React 前端模板集合。
 */
public final class FrontendReactTemplates {

    private FrontendReactTemplates() {
    }

    public static List<TemplateDescriptor> all() {
        return List.of(
                gitignore(),
                packageJson(),
                tsconfigJson(),
                tsconfigNodeJson(),
                viteConfig(),
                indexHtml(),
                mainTsx(),
                appTsx(),
                indexCss(),
                layoutComponent(),
                homePage(),
                loginPage(),
                registerPage(),
                crudPage(),
                apiModule(),
                typesModule(),
                authTypesModule(),
                envDts()
        );
    }

    private static TemplateDescriptor gitignore() {
        return TemplateDescriptor.builder()
                .id("frontend-react-gitignore")
                .templatePath("scaffold/templates/frontend/react/gitignore.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/.gitignore")
                .build();
    }

    private static TemplateDescriptor packageJson() {
        return TemplateDescriptor.builder()
                .id("frontend-react-package-json")
                .templatePath("scaffold/templates/frontend/react/package.json.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/package.json")
                .build();
    }

    private static TemplateDescriptor tsconfigJson() {
        return TemplateDescriptor.builder()
                .id("frontend-react-tsconfig-json")
                .templatePath("scaffold/templates/frontend/react/tsconfig.json.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/tsconfig.json")
                .build();
    }

    private static TemplateDescriptor tsconfigNodeJson() {
        return TemplateDescriptor.builder()
                .id("frontend-react-tsconfig-node-json")
                .templatePath("scaffold/templates/frontend/react/tsconfig.node.json.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/tsconfig.node.json")
                .build();
    }

    private static TemplateDescriptor viteConfig() {
        return TemplateDescriptor.builder()
                .id("frontend-react-vite-config")
                .templatePath("scaffold/templates/frontend/react/vite.config.ts.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/vite.config.ts")
                .build();
    }

    private static TemplateDescriptor indexHtml() {
        return TemplateDescriptor.builder()
                .id("frontend-react-index-html")
                .templatePath("scaffold/templates/frontend/react/index.html.ftl")
                .outputPathResolver(context -> resolveRoot(context) + "/index.html")
                .build();
    }

    private static TemplateDescriptor mainTsx() {
        return TemplateDescriptor.builder()
                .id("frontend-react-main-tsx")
                .templatePath("scaffold/templates/frontend/react/src/main.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "main.tsx"))
                .build();
    }

    private static TemplateDescriptor appTsx() {
        return TemplateDescriptor.builder()
                .id("frontend-react-app-tsx")
                .templatePath("scaffold/templates/frontend/react/src/App.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "App.tsx"))
                .build();
    }

    private static TemplateDescriptor indexCss() {
        return TemplateDescriptor.builder()
                .id("frontend-react-index-css")
                .templatePath("scaffold/templates/frontend/react/src/index.css.ftl")
                .outputPathResolver(context -> srcPath(context, "index.css"))
                .build();
    }

    private static TemplateDescriptor layoutComponent() {
        return TemplateDescriptor.builder()
                .id("frontend-react-layout")
                .templatePath("scaffold/templates/frontend/react/src/components/Layout.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "components/Layout.tsx"))
                .build();
    }

    private static TemplateDescriptor homePage() {
        return TemplateDescriptor.builder()
                .id("frontend-react-home-page")
                .templatePath("scaffold/templates/frontend/react/src/pages/Home.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "pages/Home.tsx"))
                .build();
    }

    private static TemplateDescriptor loginPage() {
        return TemplateDescriptor.builder()
                .id("frontend-react-login-page")
                .templatePath("scaffold/templates/frontend/react/src/pages/Login.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "pages/Login.tsx"))
                .build();
    }

    private static TemplateDescriptor registerPage() {
        return TemplateDescriptor.builder()
                .id("frontend-react-register-page")
                .templatePath("scaffold/templates/frontend/react/src/pages/Register.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "pages/Register.tsx"))
                .build();
    }

    private static TemplateDescriptor crudPage() {
        return TemplateDescriptor.builder()
                .id("frontend-react-crud-page")
                .templatePath("scaffold/templates/frontend/react/src/pages/Crud.tsx.ftl")
                .outputPathResolver(context -> srcPath(context, "pages/" + ScaffoldNameUtils.deriveFrontendReactPageComponentName(context) + ".tsx"))
                .build();
    }

    private static TemplateDescriptor apiModule() {
        return TemplateDescriptor.builder()
                .id("frontend-react-api-module")
                .templatePath("scaffold/templates/frontend/react/src/lib/api.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "lib/api.ts"))
                .build();
    }

    private static TemplateDescriptor typesModule() {
        return TemplateDescriptor.builder()
                .id("frontend-react-entity-types")
                .templatePath("scaffold/templates/frontend/react/src/types/Entity.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "types/" + context.getClassInfo().getClassName() + ".ts"))
                .build();
    }

    private static TemplateDescriptor authTypesModule() {
        return TemplateDescriptor.builder()
                .id("frontend-react-auth-types")
                .templatePath("scaffold/templates/frontend/react/src/types/Auth.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "types/auth.ts"))
                .build();
    }

    private static TemplateDescriptor envDts() {
        return TemplateDescriptor.builder()
                .id("frontend-react-env-dts")
                .templatePath("scaffold/templates/frontend/react/src/env.d.ts.ftl")
                .outputPathResolver(context -> srcPath(context, "env.d.ts"))
                .build();
    }

    private static String resolveRoot(TemplateContext context) {
        return ScaffoldNameUtils.deriveFrontendProjectName(context);
    }

    private static String srcPath(TemplateContext context, String relative) {
        return resolveRoot(context) + "/src/" + relative;
    }
}

